#include<bits/stdc++.h>
using namespace std;
char buf[(1<<21)+5],*p1,*p2;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
inline int read() {
	int x = 0, f = 0; char ch = getc();
	while(ch < '0' or ch > '9') f |= (ch == '-'), ch = getc();
	while(ch >= '0' and ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = getc();
	return f ? -x : x;
}
int __stk[128], __top;
inline void write(int x) {
    if(x < 0) putchar('-'), x = -x;
	do { __stk[++__top] = x % 10, x /= 10; } while(x);
	while (__top) putchar(__stk[__top--] + '0');
}
bool stmer;
const int N = 1e3 + 10, M = 2e6 + 10, mod = 147744151;
struct node {
    int a, b, c, d, id;
} op[M], tmp[M];
int n, m, q, ans, P;
int a[N][N], b[N];
void mul(int &x, int y) { x = 1ll * x * y % P; }
struct SEG {
    #define ls (lr << 1)
    #define rs (lr << 1 | 1)
    #define mid ((l + r) >> 1)
    int t[N << 2];
    int build(int l, int r, int lr) {
        if(l == r) return t[lr] = b[l];
        return t[lr] = 1ll * build(l, mid, ls) * build(mid + 1, r, rs) % P;
    }
    int query(int l, int r, int L, int R, int lr) {
        if(l >= L and r <= R) return t[lr];
        if(mid >= L and mid < R) return 1ll * query(l, mid, L, R, ls) * query(mid + 1, r, L, R, rs) % P;
        return mid >= L ? query(l, mid, L, R, ls) : query(mid + 1, r, L, R, rs);
    }
    #undef ls
    #undef rs
    #undef mid
} t[N];
void solve(int x, int y, int l, int r) {
    if(x > y or l > r) return;
    int mid = (x + y) >> 1;
    for(int i = 1; i <= m; i++) b[i] = 1;
    for(int i = mid; i >= x; i--) {
        for(int j = 1; j <= m; j++) mul(b[j], a[i][j]);
        t[i].build(1, m, 1);
    }
    for(int i = 1; i <= m; i++) b[i] = 1;
    for(int i = mid + 1; i <= y; i++) {
        for(int j = 1; j <= m; j++) mul(b[j], a[i][j]);
        t[i].build(1, m, 1);
    }
    int g = l, h = 0;
    for(int i = l; i <= r; i++) {
        if(op[i].c < mid) op[g++] = op[i];
        else if(op[i].a > mid) tmp[++h] = op[i];
        else {
            int res = t[op[i].a].query(1, m, op[i].b, op[i].d, 1);
            if(op[i].c > mid) mul(res, t[op[i].c].query(1, m, op[i].b, op[i].d, 1));
            ans = (ans + (res ^ op[i].id)) % mod;
        }
    }
    for(int i = 0; i < h; i++) op[g + i] =  tmp[i + 1];
    solve(x, mid - 1, l, g - 1), solve(mid + 1, y, g, g + h - 1);
}
bool edmer;
signed main() {
	freopen("tsuki.in", "r", stdin);
	freopen("tsuki.out", "w", stdout);
	cerr << "[Memory] " << (&stmer - &edmer) / 1024 / 1024 << " MB\n";
	n = read(), m = read(), P = read();
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++) a[i][j] = read();
    q = read();
    for(int i = 1; i <= q; i++) op[i] = {read(), read(), read(), read(), i};
    solve(1, n, 1, q), write(ans);
    cerr << "[Runtime] " << (double) clock() / CLOCKS_PER_SEC << " seconds";
	return 0;
} 